/*
** $Id: ldo.h,v 2.29.1.1 2017/04/19 17:20:42 roberto Exp $
** Stack and Call structure of Lua
** See Copyright Notice in lua.h
*/

#ifndef ldo_h
#define ldo_h


#include "lobject.h"
#include "lstate.h"
#include "lzio.h"


/**
 * 检查栈空间是否足够，并在需要时扩展栈空间。
 *
 * @param L Lua状态机指针。
 * @param n 需要的额外栈空间大小。
 * @param pre 在栈扩展前执行的代码块（通常用于保存栈指针）。
 * @param pos 在栈扩展后执行的代码块（通常用于恢复栈指针）。
 *
 * 说明：
 * - 如果当前栈空间不足以容纳额外的 `n` 个元素，则调用 `luaD_growstack` 扩展栈空间。
 * - `pre` 和 `pos` 允许在栈扩展前后执行自定义操作，例如保存和恢复栈指针。
 * - `condmovestack` 用于在测试中强制每次检查时重新分配栈空间。
 */
/*
** Macro to check stack size and grow stack if needed.  Parameters
** 'pre'/'pos' allow the macro to preserve a pointer into the
** stack across reallocations, doing the work only when needed.
** 'condmovestack' is used in heavy tests to force a stack reallocation
** at every check.
*/
#define luaD_checkstackaux(L, n, pre, pos)  \
  if (L->stack_last - L->top <= (n)) \
    { pre; luaD_growstack(L, n); pos; } else { condmovestack(L,pre,pos); }

/**
 * 检查 Lua 栈空间是否足够，并在必要时扩展栈空间。
 * 这是一个宏定义，通常用于内部实现，不直接暴露给用户。
 *
 * @param L Lua 状态机指针。
 * @param n 需要检查的栈空间大小。
 * @note 通常情况下，'pre' 和 'pos' 参数为空（无需保存任何内容）。
 */
/* In general, 'pre'/'pos' are empty (nothing to save) */
#define luaD_checkstack(L, n)  luaD_checkstackaux(L,n,(void)0,(void)0)

// 这段代码是一个宏定义，用于简化计算 Lua 栈中某个元素相对于栈底的偏移量。宏定义 savestack(L, p) 旨在提供一个方便的方式来获取从当前 Lua 状态 L 的栈底 L->stack 到某个特定栈元素 p 的距离。
/**
 * @brief 计算指针 p 相对于 Lua 栈底（stack）的偏移量。
 * @param L Lua 状态机指针。
 * @param p 需要计算偏移量的指针（通常是栈中的某个 TValue 指针）。
 * @return 返回指针 p 相对于栈底的字节偏移量。
 */
#define savestack(L, p)    ((char *)(p) - (char *)L->stack)
/**
 * @brief 根据偏移量 n 恢复栈中的指针。
 * @param L Lua 状态机指针。
 * @param n 相对于栈底的字节偏移量。
 * @return 返回栈中对应偏移量的 TValue 指针。
 */
#define restorestack(L, n)  ((TValue *)((char *)L->stack + (n)))


/**
 * 定义受保护函数的类型，这些函数由 'runprotected' 执行。
 * 该类型用于表示一个函数指针，接受 lua_State 指针和一个 void 指针作为参数。
 * 通常用于 Lua 内部实现中需要保护执行的函数。
 *
 * @param L 指向 lua_State 的指针，表示 Lua 状态机。
 * @param ud 用户数据指针，可以传递任意类型的数据。
 */
/* type of protected functions, to be ran by 'runprotected' */
typedef void (*Pfunc)(lua_State *L, void *ud);

LUAI_FUNC int luaD_protectedparser(lua_State *L, ZIO *z, const char *name,
                                   const char *mode);

LUAI_FUNC void luaD_hook(lua_State *L, int event, int line);

LUAI_FUNC int luaD_precall(lua_State *L, StkId func, int nresults);

LUAI_FUNC void luaD_call(lua_State *L, StkId func, int nResults);

LUAI_FUNC void luaD_callnoyield(lua_State *L, StkId func, int nResults);

LUAI_FUNC int luaD_pcall(lua_State *L, Pfunc func, void *u,
                         ptrdiff_t oldtop, ptrdiff_t ef);

LUAI_FUNC int luaD_poscall(lua_State *L, CallInfo *ci, StkId firstResult,
                           int nres);

LUAI_FUNC void luaD_reallocstack(lua_State *L, int newsize);

LUAI_FUNC void luaD_growstack(lua_State *L, int n);

LUAI_FUNC void luaD_shrinkstack(lua_State *L);

LUAI_FUNC void luaD_inctop(lua_State *L);

LUAI_FUNC l_noret luaD_throw(lua_State *L, int errcode);

LUAI_FUNC int luaD_rawrunprotected(lua_State *L, Pfunc f, void *ud);

#endif

